#pragma once

#include <iostream>
#include <fstream>
#include <string>
#include <sys/stat.h>
#include <jsoncpp/json/json.h>
#include <memory>

#include "Log.hpp"

using namespace log_ns;

namespace aod
{
    class FileUtil
    {
    private:
        std::string _name;  // 文件路径名称
    public:
        FileUtil(const std::string &name)
            :_name(name)
        {} 
        // 判断文件是否存在
        bool Exists()
        {
            int ret = access(_name.c_str(), F_OK);
            if(ret != 0)
            {
                LOG(WARING, "The file %s not exists\n", _name.c_str());
                return false;
            }
            return true;
        }

        // 判断文件大小
        size_t Size()
        {
            if(!this->Exists())
            {
                return 0;
            }
            struct stat st;
            size_t ret = ::stat(_name.c_str(), &st);
            if(ret != 0)
            {
                LOG(INFO, "Get file %s stat failed\n", _name.c_str());
                return 0;
            }
            return st.st_size;
        }

        // 获取文件内容
        bool GetContent(std::string& content)
        {
            if(!this->Exists()) return false;

            std::ifstream ifs;
            ifs.open(_name, std::ios::in | std::ios::binary);
            if(ifs.is_open() == false)
            {
                LOG(WARING, "ifs open file %s failed\n", _name.c_str());
                return false;
            }
            size_t ret = this->Size();
            content.resize(ret);
            ifs.read(&content[0], ret);
            if(ifs.good() == false)
            {
                LOG(WARING, "Read file %s content failed\n", _name.c_str());
                ifs.close();
                return false;
            }
            ifs.close();
            return true;
        }

        // 向文件写入内容，如果文件不存在则创建
        bool SetContent(const std::string& content)
        {
            std::ofstream ofs;
            ofs.open(_name.c_str(), std::ios::out | std::ios::binary);
            if(ofs.is_open() == false)
            {
                LOG(WARING, "ofs open file %s failed\n", _name.c_str());
                return false;
            }
            ofs.write(content.c_str(), content.size());
            if(ofs.good() == false)
            {
                LOG(WARING, "Read file %s content failed\n", _name.c_str());
                ofs.close();
                return false;
            }
            ofs.close();
            return true;
        }
        bool CreateDirectory()
        {
            if(this->Exists())
            {
                return true;
            }
            mkdir(_name.c_str(), 0777); //创建目录，并设置其权限为可读可写可运行
            return true;
        }
    };
    
    class JsonUtil
    {
    public:
        static bool Serialize(const Json::Value& value, std::string& body)
        {
            Json::StreamWriterBuilder swb;
            std::unique_ptr<Json::StreamWriter> sw(swb.newStreamWriter());

            std::stringstream ss;
            int ret = sw->write(value, &ss);
            if(ret != 0)
            {
                LOG(WARING, "Searilize failed\n");
                return false;
            }
            body = ss.str();
            return true;
        }

        static bool UnSerialize(Json::Value& value, const std::string body)
        {
            Json::CharReaderBuilder crb;
            std::unique_ptr<Json::CharReader> cr(crb.newCharReader());

            std::string serr;
            bool ret = cr->parse(body.c_str(), body.c_str() + body.size(), &value, &serr);
            if(ret == false)
            {
                LOG(WARING, "Unsearilize failed\n");
                return false;
            }
            return true;
        }

    };
};